home *** CD-ROM | disk | FTP | other *** search
/ Total Network Tools 2002 / NextStepPublishing-TotalNetworkTools2002-Win95.iso / Archive / Misc Servers / Zope.exe / UNITTEST.TXT < prev    next >
Encoding:
Text File  |  2000-09-23  |  14.2 KB  |  304 lines

  1. Zope Unit Testing
  2.  
  3.  Zope Testing
  4.  
  5.   If you encounter a directory named "tests" in a package within
  6.   within the Zope source code, it most likely indicates that the
  7.   directory contains test code used to ensure that the code owned by
  8.   the package works as it was designed.  Many of the test scripts
  9.   contained within Zope "tests" directories will be scripts which
  10.   contain "unit tests".
  11.  
  12.  What Unit Tests Are
  13.  
  14.   A "unit" may be defined as a piece of code with a single intended
  15.   purpose.  A "unit test" is defined as a piece of code which exists
  16.   to codify the intended behavior of a unit and to compare its
  17.   intended behavior against its actual behavior.
  18.  
  19.   Unit tests are a way for developers and quality assurance engineers
  20.   to quickly ascertain whether independent units of code are working as
  21.   expected.  Unit tests are generally written at the same time as the
  22.   code they are intended to test.  A unit testing framework allows a
  23.   collection of unit tests to be run without human intervention,
  24.   producing a minimum of output if all the tests in the collection are
  25.   successful.
  26.  
  27.  What Unit Tests Are Not
  28.  
  29.   It's very useful to define unit tests in terms of what they are
  30.   not.  From the "Extreme Programming Enthusiast" website
  31.   (http://c2.com/cgi/wiki?UnitTestsDefined)::
  32.  
  33.    Unit tests are not:
  34.  
  35.     - Manually operated.
  36.  
  37.     - Automated screen-driver tests that simulate user input (these
  38.       are "functional tests").
  39.  
  40.     - Interactive.  They run "no questions asked."
  41.  
  42.     - Coupled.  They run without dependencies except those native to
  43.       the thing being tested.
  44.  
  45.     - Complicated.  Unit test code is typically straightforward
  46.       procedural code that simulates an event.
  47.  
  48.  Unit Testing Frameworks
  49.  
  50.   A unit testing framework is generally employed to collect related
  51.   unit tests together in order to make it easier to run them as a
  52.   group.  When used with a unit testing framework, unit tests live
  53.   outside of the modules of code they're intended to test.
  54.  
  55.  How Unit Tests Help In The Development Process
  56.  
  57.   Unit tests should be written at the same time the code they test is
  58.   written.  A short, healthy cycle of "code/write test/run
  59.   test/repeat" can help a developer code more quickly by reducing
  60.   "backtracking" effort and by helping the developer focus on the
  61.   actual problem at hand.  Additonally, the unit tests generated at
  62.   initial development time can serve as later assurance that
  63.   maintenance and refactoring performed on code does not break any of
  64.   its intended functionality or behavior.  The results of unit tests
  65.   may additionally be used as a metric by quality assurance personnel
  66.   along with the results of other tests to gauge code quality before
  67.   before it is "shipped."
  68.  
  69.  Basic Unit Testing Philosophies
  70.  
  71.   Write unit tests at the same time that you write the code.
  72.   Nothing's worse than being faced with the prospect of writing tests
  73.   against a huge chunk of existing code because you "have to."
  74.   Writing unit tests post-facto can be boring and also robs you of the
  75.   main benefits that unit testing can provide.  Writing unit tests at
  76.   the same time you write the code helps you focus on the task at
  77.   hand.  Writing unit tests in conjuction with code can be fun and
  78.   satisfying, and can help you improve the quality of your code while
  79.   its goals are fresh in your mind.  Used properly, unit testing may
  80.   also help you write code faster, because you will need to
  81.   "backtrack" less.  Some "Extreme Programming" enthusiasts posit that
  82.   you should write a test before you write its associated code, and
  83.   then develop the code until it passes the test.
  84.  
  85.   Unit tests should be developed against as small and specific a
  86.   subset of a system's or subsystem's functionality as possible.  For
  87.   instance, a one unit test may test that a unique id generator
  88.   produces ids of a specific length, while another unit test in the
  89.   same group may ensure that a thousand ids from the same unique id
  90.   generator do not contain the same value.  Writing a single unit test
  91.   which tests a broad swath of a system's capabilities is
  92.   counterproductive, because it does not allow for a fine enough
  93.   granularity when attempting to figure out "what went wrong,"
  94.   requiring the developer to "backtrack".  Unit testing is capable of
  95.   helping to help reduce backtracking, but only if used properly.
  96.  
  97.   A unit test does not produce any output unless it fails.  If a unit
  98.   test fails, it should print something useful, but short.  A unit
  99.   test should never fill the screen with output or otherwise produce
  100.   output that needs to be manually examined for "clues".  This is the
  101.   realm of other testing methodologies.  If unit tests are written at
  102.   sufficiently granular level, it is often enough just to know the
  103.   name of the unit test that failed.
  104.  
  105.   "It is better to have tried to test and failed than to not have
  106.   tried to test at all" aka "test the riskist things first."  If the
  107.   prospect of writing a series of unit tests for an existing system
  108.   seems daunting, it's important to remember that no matter how many
  109.   unit tests you write, you cannot prove that your software does not
  110.   have bugs.  Therefore, you cannot possibly test every case while
  111.   developing.  You should plan to write tests against code based on
  112.   the risks involved in not testing that code.  Don't feel that you
  113.   need to write a test case for every "corner case" (although do try
  114.   to hit the riskiest ones).  In the worst case, it's better to have a
  115.   test module with one lonely unit test in it than none at all.
  116.  
  117.   "Test fixtures" are employed by unit tests.  Test fixtures are bits
  118.   of state and environment that allow the unit test to perform its job
  119.   properly.  An example of a test fixture might be a file, an instance
  120.   of a class, or a row in a database table.  Any part of the
  121.   environment needed by a unit test besides the unit testing framework
  122.   itself is considered a test fixture.
  123.  
  124.   In general, the common fixtures required by individual tests in a
  125.   testing group should be more or less identical.  If the fixtures
  126.   needed by a single test are radically different than the fixtures
  127.   required by the rest of the tests, or if the test does not require
  128.   the fixtures provided to the other tests, it probably belongs in
  129.   another (or its own) group of tests.
  130.  
  131.   When a unit test in a group modifies the state of a test fixture,
  132.   the test fixture should be restored to a known state before the next
  133.   unit test in the group is run.  Often, this means "rolling back"
  134.   changes to a transactional database or restoring the state of a
  135.   string so the next unit test can inherit a known state of the same
  136.   fixtures.  The unit testing framework has capabilities which allow
  137.   you to automate most of this work by providing a "set up" method
  138.   which gets called before each test is run and a "tear down" method
  139.   that gets called after a test is finished.
  140.  
  141.   Unit tests should play nicely with the unit testing framework they
  142.   employ.  Unit tests should not call "sys.exit()" or do similar
  143.   things which effect their ability to be run as part of a group of
  144.   tests.  The testing framework attempts to deal with misbehaved unit
  145.   tests, but it's better just to make them behave nicely in the first
  146.   place.
  147.  
  148.   Unit tests should "grow" with the code that they're intended to
  149.   test.  For example, if a group of unit tests is intended to verify
  150.   the behavior of all of the routines within a module, additional unit
  151.   tests should be added to the test group when new functionality is
  152.   added to that module.
  153.  
  154.  Writing Unit Tests For The Zope Core
  155.  
  156.   If you're writing core code, you probably don't need to listen to
  157.   any more of this.  :-) The rules for writing tests for Zope core
  158.   code are simple:
  159.  
  160.    - The testing code should make use of PyUnit
  161.      (/lib/python/unittest.py).  Instructions for using PyUnit are
  162.      available at http://pyunit.sourceforge.net.
  163.  
  164.    - Tests must be placed in a "tests" subdirectory of the package or
  165.      directory in which the core code you're testing lives.
  166.  
  167.    - Test modules should be named something which represents the
  168.      functionality they test, and should begin with the prefix "test."
  169.      E.g., a test module for BTree should be named testBTree.py.
  170.  
  171.    - An individual test module should take no longer than 60 seconds
  172.      to complete.
  173.  
  174.  Writing Unit Tests For Applications Based On Zope
  175.  
  176.   Zope uses the PyUnit unit testing framework, the documentation for
  177.   which is available at http://pyunit.sourceforge.net.  The
  178.   lib/python/unittest.py module is the framework.  You should
  179.   establish your own conventions for naming and placement of test
  180.   modules.
  181.  
  182.   Writing unit tests against applications based on Zope can be
  183.   difficult.  Zope is a collection of related modules, some with
  184.   non-trivial interdependencies.  Running its code successfully also
  185.   in some cases depends on state provided only in the context of a web
  186.   request, so calling Zope methods directly may not work as you
  187.   expect.  If you're not intimately familiar with Zope, implementing
  188.   unit tests can be fustrating.  For example, for the common case,
  189.   before you are able to write code which tests a Zope SQL Method, you
  190.   must establish a test fixture which represents your entire Zope
  191.   site.
  192.  
  193.   Luckily, some tools are at your disposal to make writing unit tests
  194.   against Zope components and applications easier by making the
  195.   creation of these fixtures easier.
  196.  
  197.   Surprisingly, one of the most effective tools for facilitating unit
  198.   testing is ZEO (http://www.zope.org/Products/ZEO).  ZEO is an
  199.   open-source clustering solution for Zope which makes it possible to
  200.   front-end a single "storage server" which manages a Zope object
  201.   database with multiple Zope clients that run a "client storage".
  202.   The reason ZEO is interesting for unit testing is mostly an
  203.   unintended side-effect of how it works as compared to Zope without
  204.   ZEO.  Zope without ZEO commonly uses a "FileStorage" to hold its
  205.   object database.  When Zope is started with a FileStorage, the
  206.   FileStorage code processes an "index" file.  This takes time.  Zope
  207.   using a ClientStorage as with ZEO does not process an index file,
  208.   making startup faster.  Fast startup of Zope is critical to
  209.   effective unit testing.  It is recommended that you implement ZEO if
  210.   you're heavy in to unit testing, as it really speeds things up.
  211.   It's not strictly required, however.
  212.  
  213.   Making Zope itself into a test fixture is straightforward.  Your
  214.   test code must:
  215.  
  216.    - add the 'lib/python' directory of your Zope installation to the
  217.      PYTHONPATH (via sys.path.insert())
  218.  
  219.    - 'import ZODB' (may not be required, but just put it in for good measure)
  220.  
  221.    - 'import Zope'
  222.  
  223.    - 'app = Zope.app()'
  224.  
  225.    - operate on the Zope instance space by calling methods from the
  226.      root object (bound to 'app'), e.g.:
  227.  
  228.      app.acl_users.manage_addUser(<parameters>)
  229.  
  230.    - a transaction will not be committed to the Zope object database
  231.      until you call the global function "get_transaction().commit()",
  232.      so changes made to the ZODB are not visible to succeeding tests
  233.      unless that function is called explicitly.
  234.  
  235.    - As a part of your tearDown, make sure to call
  236.      "app._p_jar.close()".  This closes the database connection
  237.      cleanly.
  238.  
  239.   For more information on operating on Zope programatically by
  240.   "importing" it, see Michel Pelletier's "The Debugger Is Your
  241.   Friend" at
  242.   http://www.zope.org/Members/michel/HowTos/TheDebuggerIsYourFriend
  243.  
  244.   Sometimes, just importing Zope isn't enough.  For example, it's
  245.   often not possible to obtain the results of a DTML or Python method
  246.   by simply calling it from your running code without doing lots of
  247.   trickery by establishing fake REQUEST object to pass in to it, as
  248.   Zope expects a REQUEST object to exist in the context of a web
  249.   request (which a DTML method is somewhat logically designed to
  250.   serve).
  251.  
  252.   If you find yourself getting bogged down while writing unit tests by
  253.   Zope's refusal to run certain methods due to missing state (like
  254.   REQUEST), it's useful to know about the "debug" method of the Zope
  255.   package.  This method allows you to simulate a web request, which
  256.   generally provides all the state necessary to run methods which
  257.   depend on web requests, and returns the results of the web request
  258.   as it would be seen in by a web browser.  To use the Zope debug
  259.   method, do the following:
  260.  
  261.    - add the lib/python path to your PYTHONPATH (via sys.path.insert())
  262.  
  263.    - 'import ZODB'
  264.  
  265.    - 'import Zope'
  266.   
  267.    - 'Zope.debug('/a/url/representing/a/method?with=a?couple=arguments',
  268.                  u='username:password', s='silent', e={'some':'environment',
  269.                  'variable':'settings'})
  270.  
  271.   The "silent" option causes Zope not to print anything.  You can set
  272.   your python's stdout to a file or a file-like object to capture the
  273.   output if you do not set the silent flag.
  274.  
  275.   In Zope versions before 2.2.2, all calls to Zope.debug commit the
  276.   transaction represented by the call to Zope.debug by default.  This
  277.   can pose problems for unit testing, as the state of the environment
  278.   should not be effected by prior tests.  A solution should be
  279.   available by the release of Zope 2.3.
  280.  
  281.  Administrivia
  282.  
  283.   Unit test scripts found in the Zope source code currently make use
  284.   of the PyUnit unit testing framework, available from
  285.   http://pyunit.sourceforge.net, written by Stephen Purcell (thanks
  286.   Stephen!).  PyUnit is based on the JUnit testing framework for Java
  287.   (written by Kent Beck and Erich Gamma), which in turn was based on a
  288.   testing framework designed for Smalltalk (also written by Kent
  289.   Beck).
  290.  
  291.   Unit testing is a primary tenet of "Extreme Programming", a software
  292.   development methodology designed to faciliate the rapid production
  293.   of high quality code with a minimum of developmental ceremony.  For
  294.   more information on unit tests as they relate to Extreme
  295.   Programming, see http://c2.com/cgi/wiki?UnitTestsDefined.  Although
  296.   Digital Creations has not embraced the entire spectrum of Extreme
  297.   Programming methodologies in its software development process, we've
  298.   found unit tests a way to speed development and produce
  299.   higher-quality code.
  300.  
  301.  
  302.  
  303.  
  304.